package com.base.game.entity;

import com.base.engine.graphics.Vertex3f;
import com.base.engine.system.EDirection;
import com.base.game.physics.Physics;

import static org.lwjgl.opengl.GL11.*;

public class Camera {
	
	public final float SPEED = 1f ; 
	public final float HEIGHT = 2.0f ; 
	private final Physics physics; 
	private float yaw, pitch; 
	private Vertex3f pos = new Vertex3f(0,0,0) ; 
	
	
	public float getYaw(){
		return yaw ; 
	}
	
	public float getPitch(){
		return pitch ; 
	}
	
	public Vertex3f getPos(){
		return pos ; 
	}
	
	public Camera(Physics p){
		this.physics = p ; 
	}
	
	public Camera(Physics p, Vertex3f pos){
		this(p) ; 
		this.pos = pos ; 
	}
	
	public void yaw(float val){
		this.yaw += val ; 
	}
	
	public void pitch(float val){
		this.pitch += val	; 
	}
	
	public void update(){
//		this.physics.fall(this); 
	}
	
	private void up(float distance){
		try{
			float y = pos.getY();  
			y -= distance ; 
			if(!this.physics.isColliding(this, new Vertex3f(0,-distance,0)))
				pos.setY(y);
		}catch(RuntimeException e){} 
	}
	
	private void down(float distance){
		try{
			float y = pos.getY();  
			y += distance ; 
			if(!this.physics.isColliding(this, new Vertex3f(0, distance, 0)))
				pos.setY(y);
		}catch(RuntimeException e){} 
	}
	
	private void forwards(float distance){
		try{
			float x = pos.getX(); 
			float z = pos.getZ() ;
			float deltaX = distance * (float)Math.sin(Math.toRadians(yaw)); 
			float deltaZ = distance *	(float)Math.cos(Math.toRadians(yaw)); 
			x -= deltaX ;
			z += deltaZ ;
			if(!this.physics.isColliding(this, new Vertex3f(-deltaX, 0, deltaZ))){
				pos.setX(x);
				pos.setZ(z);
			}
		}catch(RuntimeException e){} 
	}
	
	private void backwards(float distance){
		try{
			float x = pos.getX(); 
			float z = pos.getZ() ;
			float deltaX = distance * (float)Math.sin(Math.toRadians(yaw));
			float deltaZ = distance *	(float)Math.cos(Math.toRadians(yaw)); 
			x += deltaX ;  
			z -=  deltaZ ; 
			if(!this.physics.isColliding(this, new Vertex3f(deltaX, 0, -deltaZ))){
				pos.setX(x);
				pos.setZ(z);
			}
		}catch(RuntimeException e){} 
	}
	
	private void strafeLeft(float distance){
		try{
			float x = pos.getX(); 
			float z = pos.getZ() ;
			float deltaX = distance * (float)Math.sin(Math.toRadians(yaw-90));  
			float deltaZ = distance *	(float)Math.cos(Math.toRadians(yaw-90)); 
			x -= deltaX ; 
			z += deltaZ ;
			if(!this.physics.isColliding(this, new Vertex3f(-deltaX, 0, deltaZ))){
				pos.setX(x);
				pos.setZ(z);
			}
		}catch(RuntimeException e){} 
	}
	
	private void strafeRight(float distance){
		try{
			float x = pos.getX(); 
			float z = pos.getZ() ;
			float deltaX = distance * (float)Math.sin(Math.toRadians(yaw+90)); 
			float deltaZ = distance *	(float)Math.cos(Math.toRadians(yaw+90)); 
			x -= deltaX ; 
			z += deltaZ ; 
			if(!this.physics.isColliding(this, new Vertex3f(-deltaX, 0, deltaZ))){
				pos.setX(x);
				pos.setZ(z);
			}
		}catch(RuntimeException e){} 
	}
	
	public void move(EDirection dir, float speed){
			switch(dir){
				case NORTH: this.forwards(speed); break ; 
				case SOUTH: this.backwards(speed); break ; 
				case WEST: this.strafeLeft(speed); break ; 
				case EAST: this.strafeRight(speed); break ; 
				case UP: this.up(speed); break ; 
				case DOWN: this.down(speed); break ; 
		}		
	}

	public void move(EDirection dir) {
		this.move(dir, this.SPEED); 
	}
	
	public String toString(){
		return "Position absolute: ( "+pos.getX()+" | "+pos.getY()+" | "+pos.getZ()+" )" ; 
	}
	
}
